package com.zhejiangzhengyuan.municipal_common.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zhejiangzhengyuan.municipal_common.entity.*;
import com.zhejiangzhengyuan.municipal_common.mapper.*;
import com.zhejiangzhengyuan.municipal_common.response.ResponseVo;
import com.zhejiangzhengyuan.municipal_common.service.*;
import com.zhejiangzhengyuan.municipal_common.utils.ConstantUtil;
import com.zhejiangzhengyuan.municipal_common.utils.DateFormatUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;

import static com.zhejiangzhengyuan.municipal_common.utils.DateFormatUtil.getChartData;
import static com.zhejiangzhengyuan.municipal_common.utils.DateFormatUtil.getStringByTime;

/**
 * @author ZhouXiang
 * @since on 2020/1/14
 */
@Service
@Slf4j
public class BIServiceImpl implements BIService {
  @Autowired private InspectionTasksMapper inspectionTasksMapper;
  @Autowired private DeviceService deviceService;
  @Autowired private DeviceMapper deviceMapper;
  @Autowired private InspectionRecordMapper inspectionRecordMapper;
  @Autowired private InspectionEventMapper inspectionEventMapper;
  @Autowired private InspectionEventService inspectionEventService;
  @Autowired private WarnEventService warnEventService;
  @Autowired private WarnEventMapper warnEventMapper;
  @Autowired private ProblemsService problemsService;
  @Autowired private PumpStationMapper pumpStationMapper;
  @Autowired private RoadGisService roadGisService;
  @Autowired private BridgeGisService bridgeGisService;
  // 道路专题数据显示
  @Override
  public JSONObject getBICount(String type, Integer month, String granularity) {
    int frequency = 0;
    int maintain = 0;
    int report = 0;
    int resolved = 0;
    int conserve = 0;
    if (Strings.isBlank(granularity)) {
      String monthData = getChartData(month);
      frequency = inspectionTasksMapper.getFrequency(type, null, monthData);
      maintain = inspectionTasksMapper.getMaintain(type, null, monthData);
      report = inspectionTasksMapper.getReport(type, null, monthData);
      resolved = inspectionTasksMapper.getResolved(type, null, monthData);
      conserve = inspectionTasksMapper.getMaintenanceConserve(type, null, monthData);
    } else {
      int startMonth = DateFormatUtil.getStartCalendarField(granularity);
      int endMonth = DateFormatUtil.getEndCalendarField(granularity);
      while (startMonth <= endMonth) {
        String monthData = getChartData(startMonth);
        frequency += inspectionTasksMapper.getFrequency(type, null, monthData);
        maintain += inspectionTasksMapper.getMaintain(type, null, monthData);
        report += inspectionTasksMapper.getReport(type, null, monthData);
        resolved += inspectionTasksMapper.getResolved(type, null, monthData);
        conserve += inspectionTasksMapper.getMaintenanceConserve(type, null, monthData);
        startMonth++;
      }
    }

    JSONObject result = new JSONObject();
    // 生成解决率图表
    JSONArray array = new JSONArray();
    JSONObject arrayItem = new JSONObject();
    arrayItem.put("name", "解决前");
    arrayItem.put("value", maintain);
    array.add(arrayItem);
    arrayItem = new JSONObject();
    arrayItem.put("name", "解决后");
    arrayItem.put("value", resolved);
    array.add(arrayItem);
    result.put("解决率图表", array);
    // 生成维护抢修表
    array = new JSONArray();
    arrayItem = new JSONObject();
    arrayItem.put("name", "维护");
    arrayItem.put("value", conserve);
    array.add(arrayItem);
    arrayItem = new JSONObject();
    arrayItem.put("name", "事故抢修");
    arrayItem.put("value", maintain);
    array.add(arrayItem);
    result.put("报警类型表", array);
    result.put("巡检班次", frequency);
    result.put("巡检上报", report);
    result.put("抢修维护", conserve);
    return result;
  }
  // 手机端桥洞专题显示
  @Override
  public JSONArray getBridgeHole(String deviceName, Integer month) {
    String monthData = getChartData(month);
    JSONArray result = new JSONArray();
    QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<>();
    deviceQueryWrapper.eq("name", deviceName);
    Device device = deviceService.getOne(deviceQueryWrapper);
    int bridgeWarn = inspectionTasksMapper.getBridgeWarn(device.getId(), monthData);
    int bridgeResolved = inspectionTasksMapper.getBridgeResolved(device.getId(), monthData);
    JSONObject item = new JSONObject();
    item.put("name", "设备告警");
    item.put("value", bridgeWarn);
    result.add(item);
    item = new JSONObject();
    item.put("name", "解决");
    item.put("value", bridgeResolved);
    result.add(item);
    return result;
  }
  // 手机端泵站专题显示
  @Override
  public ResponseVo getPumpData(String type, Integer month, String granularity) {
    int count;
    if (Strings.isBlank(granularity)) {
      int before = 0;
      String monthData = getChartData(month);
      JSONObject result = new JSONObject();
      // 告警类型图表
      JSONArray deviceCharts = new JSONArray();
      JSONObject dataItem = new JSONObject();
      dataItem.put("name", "设备故障");
      count = inspectionTasksMapper.getPumpData(type, "设备故障", monthData);
      before += count;
      dataItem.put("value", count);
      deviceCharts.add(dataItem);
      dataItem = new JSONObject();
      dataItem.put("name", "液位异常");
      count = inspectionTasksMapper.getPumpData(type, "液位异常", monthData);
      before += count;
      dataItem.put("value", count);
      deviceCharts.add(dataItem);
      dataItem = new JSONObject();
      dataItem.put("name", "气体数据异常");
      count = inspectionTasksMapper.getPumpData(type, "数据异常", monthData);
      before += count;
      dataItem.put("value", count);
      deviceCharts.add(dataItem);
      result.put("warnTypeCharts", deviceCharts);
      // 解决率
      deviceCharts = new JSONArray();
      dataItem = new JSONObject();
      dataItem.put("name", "解决前");
      dataItem.put("value", before);
      deviceCharts.add(dataItem);
      dataItem = new JSONObject();
      dataItem.put("name", "解决后");
      dataItem.put("value", inspectionTasksMapper.getPumpResolved(type, monthData));
      deviceCharts.add(dataItem);
      result.put("resolvedCharts", deviceCharts);
      return ResponseVo.successWithData(result);
    } else {
      int sbgCount = 0; // 设备数量
      int ywCount = 0; // 液位数量
      int qiCount = 0; // 气体数量
      int after = 0;
      int startMonth = DateFormatUtil.getStartCalendarField(granularity);
      int endMonth = DateFormatUtil.getEndCalendarField(granularity);
      while (startMonth <= endMonth) {
        String monthData = getChartData(startMonth);
        sbgCount += inspectionTasksMapper.getPumpData(type, "设备故障", monthData);
        ywCount += inspectionTasksMapper.getPumpData(type, "液位异常", monthData);
        qiCount += inspectionTasksMapper.getPumpData(type, "数据异常", monthData);
        after += inspectionTasksMapper.getPumpResolved(type, monthData);
        startMonth++;
      }
      JSONObject result = new JSONObject();
      // 告警类型图表
      JSONArray deviceCharts = new JSONArray();
      JSONObject dataItem = new JSONObject();
      dataItem.put("name", "设备故障");
      dataItem.put("value", sbgCount);
      deviceCharts.add(dataItem);
      dataItem = new JSONObject();
      dataItem.put("name", "液位异常");
      dataItem.put("value", ywCount);
      deviceCharts.add(dataItem);
      dataItem = new JSONObject();
      dataItem.put("name", "气体数据异常");
      dataItem.put("value", qiCount);
      deviceCharts.add(dataItem);
      result.put("warnTypeCharts", deviceCharts);
      // 解决率
      deviceCharts = new JSONArray();
      dataItem = new JSONObject();
      dataItem.put("name", "解决前");
      dataItem.put("value", sbgCount + qiCount + ywCount);
      deviceCharts.add(dataItem);
      dataItem = new JSONObject();
      dataItem.put("name", "解决后");
      dataItem.put("value", after);
      deviceCharts.add(dataItem);
      result.put("resolvedCharts", deviceCharts);
      return ResponseVo.successWithData(result);
    }
  }

  @Override
  public ResponseVo getInspectionsBIData(String granularity) {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    Calendar calendar = Calendar.getInstance();
    String startTime = "";
    String endTime = "";
    switch (granularity) {
      case "年":
        calendar.set(Calendar.DAY_OF_YEAR, 1);
        startTime = simpleDateFormat.format(calendar.getTimeInMillis()) + " 00:00:00";
        calendar.add(Calendar.YEAR, 1);
        calendar.add(Calendar.DATE, -1);
        endTime = simpleDateFormat.format(calendar.getTimeInMillis()) + " 23:59:59";
        break;
      case "月":
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        startTime = simpleDateFormat.format(calendar.getTimeInMillis()) + " 00:00:00";
        calendar.add(Calendar.MONTH, 1);
        calendar.add(Calendar.DATE, -1);
        endTime = simpleDateFormat.format(calendar.getTimeInMillis()) + " 23:59:59";
        break;
      case "季":
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) / 3 * 3);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        startTime = simpleDateFormat.format(calendar.getTimeInMillis()) + " 00:00:00";
        calendar.add(Calendar.MONTH, 3);
        calendar.add(Calendar.DATE, -1);
        endTime = simpleDateFormat.format(calendar.getTimeInMillis()) + " 23:59:59";
        break;
    }
    JSONObject result = new JSONObject();
    result.put("inspectionRecordCount", inspectionRecordMapper.getCountByTime(startTime, endTime));
    JSONArray array = new JSONArray();
    JSONObject item = new JSONObject();
    item.put("name", "整改前");
    item.put("value", inspectionEventMapper.getBeforeActionCountByTimestamp(startTime, endTime));
    array.add(item);
    item = new JSONObject();
    item.put("name", "整改后");
    item.put("value", inspectionEventMapper.getAfterActionCountByTimestamp(startTime, endTime));
    array.add(item);
    result.put("resolvedCharts", array);

    return ResponseVo.successWithData(result);
  }

  @Override
  public ResponseVo getMaintenanceConserve() {
    JSONObject result = new JSONObject();
    JSONArray chartsData = new JSONArray();
    JSONObject item;
    // 生成道路和桥梁的养护次数表
    for (int i = 0; i < 12; i++) {
      item = new JSONObject();
      item.put("x", i + 1);
      item.put("y", inspectionTasksMapper.getMaintenanceConserve("道路", null, getChartData(i + 1)));
      chartsData.add(item);
    }
    result.put("roadCharts", chartsData);
    chartsData = new JSONArray();
    for (int i = 0; i < 12; i++) {
      item = new JSONObject();
      item.put("x", i + 1);
      item.put("y", inspectionTasksMapper.getMaintenanceConserve("桥梁", null, getChartData(i + 1)));
      chartsData.add(item);
    }
    result.put("bridgeCharts", chartsData);
    return ResponseVo.successWithData(result);
  }

  @Override
  public ResponseVo getMonitorCount() {
    JSONObject result = new JSONObject();
    // 统计当前报警数和累计报警数
    // 报警来源：设备告警 warnEvent 巡检告警 inspection_event
    QueryWrapper<WarnEvent> warnEventQueryWrapper = new QueryWrapper<>();
    warnEventQueryWrapper.eq("reset", false).eq("send_order", false);
    QueryWrapper<InspectionEvent> inspectionEventQueryWrapper = new QueryWrapper<>();
    inspectionEventQueryWrapper.eq("reset", "否").eq("send_order", false);
    result.put(
        "当前报警数",
        warnEventService.count(warnEventQueryWrapper)
            + inspectionEventService.count(inspectionEventQueryWrapper));
    result.put("累计报警数", warnEventService.count() + inspectionEventService.count());
    return ResponseVo.successWithData(result);
  }

  @Override
  public ResponseVo getSpecificWarnCount() {
    JSONArray result = new JSONArray();
    JSONObject item = new JSONObject();
    // 告警内容携带井盖的及说明是井盖倾斜相关问题
    // 井盖相关统计是雨污混排系统和井盖管理系统的设备
    item.put("name", "井盖倾斜监测");
    item.put("value", warnEventMapper.getManholeCountByReason("井盖"));
    result.add(item);
    item = new JSONObject();

    item.put("name", "井内水位异常监测");
    item.put("value", warnEventMapper.getManholeCountByReason("水位"));
    result.add(item);
    item = new JSONObject();
    // 找出水尺设备,根据水尺设备找到告警信息
    item.put("name", "积水水位监测");
    item.put("value", warnEventMapper.getWaterRulerCountByReason());
    result.add(item);
    item = new JSONObject();
    // 查询设备
    item.put("name", "泵站问题监测");
    item.put("value", warnEventMapper.getPumpWarnCount());
    result.add(item);
    item = new JSONObject();
    QueryWrapper<Problems> problemsQueryWrapper = new QueryWrapper<>();
    problemsQueryWrapper.eq("defect_type", "雨污混接");
    item.put("name", "雨污混接监测");
    item.put("value", problemsService.count(problemsQueryWrapper));
    result.add(item);
    return ResponseVo.successWithData(result);
  }

  @Override
  public ResponseVo getMapInformation() {
    // 设备告警返回集接收
    JSONObject result = new JSONObject();
    // 事件
    result.put("warnEvent", warnEventMapper.getAllDetailAndLocation());
    // 泵站和雨污水处理终端
    QueryWrapper<PumpStation> queryWrapper = new QueryWrapper<>();
    queryWrapper.like("name", "泵站");
    result.put("pumpStation", pumpStationMapper.selectList(queryWrapper));
    queryWrapper = new QueryWrapper<>();
    queryWrapper.like("name", "雨污水处理终端");
    result.put("processing", pumpStationMapper.selectList(queryWrapper));
    // 井盖:井盖系统
    result.put(
        "manholeCover",
        deviceMapper.getDetailAndLocationByType(ConstantUtil.DEVICE_TYPE.MANHOLE_COVER));
    // 污水零直排的数据为雨污混排设备
    result.put("sewage", deviceMapper.getDetailAndLocationByType(ConstantUtil.DEVICE_TYPE.SEWAGE));
    // 积水点:电子水尺信息
    result.put("waterRuler", deviceMapper.getDetailAndLocationByLikeName("水尺"));
    // 导向屏:led屏
    result.put("led", deviceMapper.getDetailAndLocationByLikeName("LED"));

    return ResponseVo.successWithData(result);
  }

  @Override
  public ResponseVo selectProblemsLineChart() {
    // 获取当前年份
    String year = DateFormatUtil.getStringByTime("yyyy", System.currentTimeMillis());
    // 匹配日期
    JSONObject object = new JSONObject();
    // 找到每一天的告警次数
    object.put("warnCountCharts", formatWarnChartsByMonth(year));
    return ResponseVo.successWithData(object);
  }

  @Override
  public ResponseVo selectDeviceWarnCharts(String granularity) {
    QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("type", ConstantUtil.DEVICE_TYPE.FLOODED_ROAD).like("name", "水尺");
    List<Device> devices = deviceMapper.selectList(queryWrapper);
    // 根据设备找到指定值
    JSONArray result = new JSONArray();
    for (Device device : devices) {
      int value = 0;
      int startMonth = DateFormatUtil.getStartCalendarField(granularity);
      int endMonth = DateFormatUtil.getEndCalendarField(granularity);
      while (startMonth <= endMonth) {
        String monthData = getChartData(startMonth);
        value += deviceMapper.selectCountByDeviceId(device.getId(), monthData);
        startMonth++;
      }
      JSONObject object = new JSONObject();
      object.put("name", device.getName());
      object.put("value", value);
      result.add(object);
    }
    return ResponseVo.successWithData(result);
  }

  @Override
  public ResponseVo municipalBI(String type, String granularity) {
    JSONObject result = new JSONObject();
    int startMonth = DateFormatUtil.getStartCalendarField(granularity);
    int endMonth = DateFormatUtil.getEndCalendarField(granularity);
    int frequency = 0;
    int report = 0;
    int conserve = 0;
    while (startMonth <= endMonth) {
      String monthData = getChartData(startMonth);
      frequency += inspectionTasksMapper.getFrequency(type, null, monthData);
      report += inspectionTasksMapper.getReport(type, null, monthData);
      conserve += inspectionTasksMapper.getMaintenanceConserve(type, null, monthData);
      startMonth++;
    }
    result.put("道路巡检总班次", frequency);
    result.put("问题上报总数", report);
    result.put("道路养护总数", conserve);
    JSONObject subData = new JSONObject();
    if (type.equals("道路")) {
      List<RoadGis> roadGisList = roadGisService.list();
      if (Objects.nonNull(roadGisList) && !roadGisList.isEmpty()) {
        for (RoadGis roadGis : roadGisList) {
          subData.put(
              roadGis.getName(),
              getItemJson(
                  type,
                  roadGis.getCode(),
                  DateFormatUtil.getStartCalendarField(granularity),
                  DateFormatUtil.getEndCalendarField(granularity)));
        }
      }
    } else {
      List<BridgeGis> bridgeGisList = bridgeGisService.list();
      if (Objects.nonNull(bridgeGisList) && !bridgeGisList.isEmpty()) {
        for (BridgeGis bridgeGis : bridgeGisList) {
          subData.put(
              bridgeGis.getName(),
              getItemJson(
                  type,
                  bridgeGis.getCode(),
                  DateFormatUtil.getStartCalendarField(granularity),
                  DateFormatUtil.getEndCalendarField(granularity)));
        }
      }
    }
    result.put("subData", subData);
    return ResponseVo.successWithData(result);
  }

  // 系统告警折线图
  private JSONArray formatWarnChartsByMonth(String year) {
    String hourPattern = "yyyy-MM-dd HH:mm:ss";
    // 根据找到月份
    Calendar calendar = Calendar.getInstance();
    calendar.clear();
    calendar.set(Calendar.YEAR, Integer.parseInt(year));
    JSONArray result = new JSONArray();
    for (int i = 0; i < 12; i++) {
      JSONObject object = new JSONObject();
      calendar.set(Calendar.MONTH, i);
      String startTime =
          getStringByTime(
              hourPattern,
              DateFormatUtil.getStartTimeByPeriod("monthly", calendar.getTimeInMillis()));
      String endTime =
          getStringByTime(
              hourPattern,
              DateFormatUtil.getEndTimeByPeriod("monthly", calendar.getTimeInMillis()));
      log.info("startTime{},endTime{}", startTime, endTime);
      object.put("day", i);
      object.put("value", deviceMapper.selectCountByTime(startTime, endTime));
      result.add(object);
    }
    return result;
  }

  private JSONObject getItemJson(
      String type, String targetId, Integer startMonth, Integer endMonth) {
    int frequency = 0;
    int maintain = 0;
    int report = 0;
    int resolved = 0;
    int conserve = 0;
    while (startMonth <= endMonth) {
      String monthData = getChartData(startMonth);
      frequency += inspectionTasksMapper.getFrequency(type, targetId, monthData);
      maintain += inspectionTasksMapper.getMaintain(type, targetId, monthData);
      report += inspectionTasksMapper.getReport(type, targetId, monthData);
      resolved += inspectionTasksMapper.getResolved(type, targetId, monthData);
      conserve += inspectionTasksMapper.getMaintenanceConserve(type, targetId, monthData);
      startMonth++;
    }

    JSONObject result = new JSONObject();
    // 生成解决率图表
    JSONArray array = new JSONArray();
    JSONObject arrayItem = new JSONObject();
    arrayItem.put("name", "解决前");
    arrayItem.put("value", maintain);
    array.add(arrayItem);
    arrayItem = new JSONObject();
    arrayItem.put("name", "解决后");
    arrayItem.put("value", resolved);
    array.add(arrayItem);
    result.put("解决率图表", array);
    result.put("巡检班次", frequency);
    result.put("巡检上报", report);
    result.put("抢修维护", conserve);
    return result;
  }
}
